﻿using Heroius.Extension;
using Heroius.Files.XDB;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using XmlDatabase.Core;

namespace Heroius.Indexer
{
    public partial class FormIndexer : Form
    {
        public FormIndexer(string[] StartParams = null)
        {
            InitializeComponent();
            xdb = new XDBObj(new DirectoryInfo(@".\temp"));

            #region 指令

            #region 新建项目
            cwnew = new Heroius.Extension.Command("创建空的项目", (s, e) =>
            {
                stacreating = true;
                SaveProj.ShowDialog();
            });
            cwnew.RegistTrigger(BtnNew);
            cwnew.RegistTrigger(MiNewProj);
            cwnew.Enabled = true;
            #endregion
            #region 打开项目
            cwopen = new Heroius.Extension.Command("打开索引项目", (s, e) =>
            {
                OpenProj.ShowDialog();
            });
            cwopen.RegistTrigger(BtnOpen);
            cwopen.RegistTrigger(MiOpenProj);
            cwopen.Enabled = true;
            #endregion
            #region 合并项目
            cwmerge = new Heroius.Extension.Command("打开且合并到此项目", (s, e) =>
            {
#if LIC
                if (ActivatorHelper.licensed && ActivatorHelper.lic.ProductFeatures > 2)
                    MergeProj.ShowDialog();
                else MessageBox.Show("您目前使用的版本不支持合并项目，请获取注册码激活您的应用程序。");
#else
                MergeProj.ShowDialog();
#endif
            });
            cwmerge.RegistTrigger(BtnMerge);
            cwmerge.RegistTrigger(MiMerge);
            cwmerge.Enabled = false;
            #endregion
            #region 更改项目标题
            cwtitle = new Heroius.Extension.Command("修改项目标题", (s, e) =>
            {
                using (var tt = new TxTitle(ProjecTitle.Text))
                {
                    tt.FormClosing += (ss, ee) =>
                    {
                        if (tt.Changed)
                        {
                            ProjecTitle.Text = tt.ChangedTitle;
                            proj.Title = tt.ChangedTitle;
                            xdb.Database.Store(proj);
                            stachanged = true;
                        }
                    };
                    tt.ShowDialog();
                }
            });
            cwtitle.RegistTrigger(BtnTitle);
            cwtitle.RegistTrigger(MiTitle);
            cwtitle.Enabled = false;
            #endregion
            #region 保存项目
            cwsave = new Heroius.Extension.Command("保存当前项目", (e, s) =>
            {
                stachanged = false;

                if (File.Exists(CurrentFile))
                {
                    File.Delete(CurrentFile);
                }
                xdb.Save();
            });
            cwsave.RegistTrigger(BtnSave);
            cwsave.RegistTrigger(MiSaveProj);
            cwsave.Enabled = false;
            #endregion
            #region 另存项目
            cwsavas = new Heroius.Extension.Command("另存当前项目", (e, s) =>
            {
                stacreating = false;
                SaveProj.ShowDialog();
            });
            cwsavas.RegistTrigger(BtnSaveas);
            cwsavas.RegistTrigger(MiSavas);
            cwsavas.Enabled = false;
            #endregion

            #region 查询条目
            cwquery = new Heroius.Extension.Command("新建查询", (s, e) =>
            {
                TxQuery tt = new TxQuery();
                tt.FormClosing += (ss, ee) =>
                {
                    if (tt.Exec)
                    {
                        IEnumerable<DbItem> items = null;
                        var qresult = xdb.Database.Query<DbItem>();
                        if (qresult != null && qresult.Count() > 0)
                        {
                            if (tt.ByID)
                            {
                                items = from i in qresult where i.ID == tt.IDText select i;
                            }
                            else if (tt.ShowAll)
                            {
                                items = from i in qresult select i;
                            }
                            else
                            {
                                if (tt.WithCata)
                                {
                                    items = from i in qresult where i.Cata.Like(tt.CataText) select i;
                                }
                                if (tt.WithKey)
                                {
                                    items = from i in tt.WithCata ? items : qresult where TxItem.StringKey(i.Keywords).Contains(tt.KeyText) select i;
                                }
                            }
                        }
                        if (items != null)
                        {
                            gridsource = new BindingList<DbItem>(items.ToList());
                            Grid.DataSource = gridsource;
                        }
                    }
                };
                tt.ShowDialog();
            });
            cwquery.RegistTrigger(BtnQuery);
            cwquery.RegistTrigger(MiQuery);
            cwquery.Enabled = false;
            #endregion
            #region 添加条目
            cwadd = new Heroius.Extension.Command("添加条目", (s, e) =>
            {
                TxItem tt = new TxItem();//creating new...
                tt.FormClosing += (ss, ee) =>
                {
                    if (tt.Changed)
                    {
                        xdb.Database.Store(tt.Target);
                        stachanged = true;
                        if (gridsource == null)
                        {
                            gridsource = new BindingList<DbItem>();
                            Grid.DataSource = gridsource;
                        }
                        gridsource.Add(tt.Target);
                        Grid.Refresh();
                    }
                };
                tt.ShowDialog();
            });
            cwadd.RegistTrigger(BtnAdd);
            cwadd.RegistTrigger(MiNewItem);
            cwadd.Enabled = false;
            #endregion
            #region 编辑条目
            cwedit = new Heroius.Extension.Command("编辑当前条目", (s, e) =>
            {
                TxItem tt = new TxItem(true, GetSelectedItem());
                tt.FormClosing += (ss, ee) =>
                {
                    if (tt.Changed)
                    {
                        xdb.Database.Store(tt.Target);
                        stachanged = true;

                        var row = Grid.SelectedRows[0];

                        row.Cells[1].Value = tt.Target.Cata;
                        row.Cells[2].Value = tt.Target.Content;
                        row.Cells[3].Value = tt.Target.Link;
                        row.Cells[4].Value = tt.Target.Keywords;
                        //Grid.Refresh();
                    }
                };
                tt.ShowDialog();
            });
            cwedit.RegistTrigger(BtnEdit);
            cwedit.RegistTrigger(MiEditItem);
            cwedit.Enabled = false;
            #endregion
            #region 删除条目
            cwdel = new Heroius.Extension.Command("删除当前条目", (s, e) =>
            {
                if (MessageBox.Show("确定要删除选中记录？", "注意", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                {
                    DbItem tar = GetSelectedItem();
                    string id = tar.ID;
                    xdb.Database.Delete(tar);
                    stachanged = true;

                    Grid.Rows.Remove(Grid.SelectedRows[0]);
                }
            });
            cwdel.RegistTrigger(MiDelItem);
            cwdel.RegistTrigger(BtnDel);
            cwdel.Enabled = false;
            #endregion

            #region 生成索引树
            cwgen = new Heroius.Extension.Command("重新生成索引树", (s, e) =>
            {
                //create tree using shown items (gridsource)
                if (gridsource == null || gridsource.Count <= 0)
                {
                    MessageBox.Show("可见条目集合为空");
                    return;
                }
                Cursor = Cursors.WaitCursor;
                StateLabel.Text = "正在收集关键词……";
                var gsl = gridsource.ToList();
                var messwords = (from i in gsl select TxItem.StringKey(i.Keywords));
                List<string> listedwords = new List<string>();
                foreach (var item in messwords)
                {
                    listedwords.AddRange(item);
                }
                messwords = null;//throw it away
                var allwords = listedwords.Distinct().OrderBy(ss => ss);
                listedwords = null;//throw it away
                int c = allwords.Count();
                int ii = 1;
                TreeMe.Nodes.Clear();
                foreach (var item in allwords)
                {
                    StateLabel.Text = string.Format("正在构建索引树({0}/{1})", ii, c);
                    ii++;
                    TreeNode pnode = new TreeNode(item,
                    (from it in gsl
                     where TxItem.StringKey(it.Keywords).Contains(item)
                     select
                         new TreeNode(string.Format("{0}:{1}", it.Cata, it.Content))).OrderBy(ss => ss.Text).ToArray());
                    TreeMe.Nodes.Add(pnode);
                }
                StateLabel.Text = string.Format("最近构建：{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                Cursor = Cursors.Default;
                MessageBox.Show("更新完成");
                TreeMe.ExpandAll();
            });
            cwgen.RegistTrigger(BtnGen);
            cwgen.RegistTrigger(MiTree);
            cwgen.Enabled = false;
            #endregion
            #region 导出文档
            cwdoc = new Heroius.Extension.Command("导出文档", (s, e) =>
            {
                if (TreeMe.Nodes.Count > 0)
                {
                    RtbMe.Clear();
                    string enter = "\n";
                    Font ContentFont = new Font(RtbMe.Font.FontFamily, 10.5f);
                    Font KeyFont = new Font(RtbMe.Font.FontFamily, 12f, FontStyle.Bold);
                    RtbMe.SelectionFont = new System.Drawing.Font(RtbMe.Font.FontFamily, 18f, System.Drawing.FontStyle.Bold);
                    RtbMe.AppendText(ProjecTitle.Text);
                    RtbMe.AppendText(enter);
                    RtbMe.SelectionFont = ContentFont;
                    RtbMe.AppendText(DateTime.Now.ToString());
                    RtbMe.AppendText(enter);
                    RtbMe.AppendText(enter);
                    //limits
#if LIC
                    int limits = 50;
                    if (ActivatorHelper.licensed)
                    {
                        if (ActivatorHelper.lic.ProductFeatures > 2) limits = 0;
                        else limits = 1000;
                    }
#else
                    int limits = 0;
#endif
                    for (int i = 0; i < TreeMe.Nodes.Count; i++)
                    {
                        if (limits > 0)
                        {
                            if (i >= limits)
                            {
                                MessageBox.Show(string.Format("当前节点数已超过版本限制：{0}\n请激活完整版以自由的使用！", limits));
                                break;
                            }
                        }
                        RtbMe.SelectionFont = KeyFont;
                        RtbMe.AppendText(TreeMe.Nodes[i].Text);
                        RtbMe.AppendText(enter);
                        RtbMe.SelectionBullet = true;
                        RtbMe.SelectionIndent = 10;
                        for (int j = 0; j < TreeMe.Nodes[i].Nodes.Count; j++)
                        {
                            RtbMe.SelectionFont = ContentFont;
                            RtbMe.AppendText(TreeMe.Nodes[i].Nodes[j].Text.Replace("\n", " ").Replace("\r", " "));
                            RtbMe.AppendText(enter);
                        }
                        RtbMe.SelectionBullet = false;
                        RtbMe.SelectionIndent = 0;
                        RtbMe.AppendText(enter);
                    }
                }
                else
                {
                    MessageBox.Show("索引树尚无内容可供导出");
                }
            });
            cwdoc.RegistTrigger(MiDoc);
            cwdoc.RegistTrigger(BtnDoc);
            cwdoc.Enabled = true;
            #endregion

#if LIC
            cwactivate = new Command("激活程序", (ss, ee) =>
            {
                ActivatorHelper.TryActivate();
            });
            cwactivate.RegistTrigger(MiActivate);
#else
            MiActivate.Visible = false;
#endif

            #endregion

            Action cchange = new Action(() =>
            {
#if LIC
                if (ActivatorHelper.licensed)
                {
                    cwactivate.Enabled = (ActivatorHelper.lic.ProductFeatures <= 2);
                    this.Text = "Heroius 索引管理器";
                }
                else this.Text = "Heroius 索引管理器 (试用版)";
#else
                this.Text = "Heroius 索引管理器";
#endif
            });
            cchange();
#if LIC
            ActivatorHelper.licChanged += cchange;
#endif

            if (StartParams != null && StartParams.Length > 0)
            {
                try
                {
                    xdb.Open(StartParams[0]);
                    //fill info
                    proj = (from p in xdb.Database.Query<DbProj>() select p).First();
                    ProjecTitle.Text = proj.Title;
                    staopened = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        /// <summary>
        /// command
        /// </summary>
        Heroius.Extension.Command cwnew, cwopen, cwmerge, cwtitle, cwsave, cwsavas, cwquery, cwadd, cwedit, cwdel, cwgen, cwdoc, cwactivate;

        #region 状态

        /// <summary>
        /// 指示是否已经打开了某个项目
        /// </summary>
        bool staopened
        {
            get { return _staopened; }
            set
            {
                _staopened = value;
                cwmerge.Enabled = value;
                cwtitle.Enabled = value;
                cwsave.Enabled = value;
                cwsavas.Enabled = value;
                cwquery.Enabled = value;
                cwadd.Enabled = value;
                cwgen.Enabled = value;
            }
        }
        bool _staopened = false;
        /// <summary>
        /// 指示在保存项目对话框唤出时，是否以新建模式执行
        /// </summary>
        bool stacreating = false;
        /// <summary>
        /// 指示是否已经选择可用的条目
        /// </summary>
        bool staselected
        {
            get { return _staselected; }
            set
            {
                _staselected = value;
                cwedit.Enabled = value;
                cwdel.Enabled = value;
            }
        }
        bool _staselected = false;
        /// <summary>
        /// 指示项目内容是否经过修改
        /// </summary>
        bool stachanged = false;

        #endregion

        #region 全局实例

        /// <summary>
        /// 当前数据库
        /// </summary>
        XDBObj xdb;
        /// <summary>
        /// 当前项目记录实例
        /// </summary>
        DbProj proj;
        /// <summary>
        /// 当前打开项目的文件全路径
        /// </summary>
        string CurrentFile { get { return xdb.CurrentFile; } }
        /// <summary>
        /// 绑定源，对应于当前活动的条目列表
        /// </summary>
        BindingList<DbItem> gridsource;

        #endregion

        #region Proj-rela event handlers

        private void SaveProj_FileOk(object sender, CancelEventArgs e)
        {
            if (stacreating)
            {
                if (staopened)
                {
                    if (MessageBox.Show("将关闭当前项目", "注意", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                    {
                        if (stachanged)
                        {
                            switch (MessageBox.Show("是否保存项目", "注意", MessageBoxButtons.YesNoCancel))
                            {
                                case System.Windows.Forms.DialogResult.OK:
                                    cwsave.Excute();
                                    break;
                                case System.Windows.Forms.DialogResult.No:
                                    break;
                                case System.Windows.Forms.DialogResult.Cancel:
                                    return;
                            }
                        }
                        xdb.Close();
                    }
                    else return;
                }

                if (gridsource != null)
                {
                    gridsource.Clear();
                }
                //creating...
                xdb.Open(SaveProj.FileName);
                staopened = true;
                proj = new DbProj() { Title = "新索引项目" };
                ProjecTitle.Text = proj.Title;
                xdb.Database.Store(proj);
                xdb.Save();//将默认项目保存到文件
            }
            else
            {
                //save as...
                cwsave.Excute();
                File.Copy(CurrentFile, SaveProj.FileName);
            }
        }

        private void OpenProj_FileOk(object sender, CancelEventArgs e)
        {
            if (staopened)
            {
                if (MessageBox.Show("将关闭当前项目", "注意", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                {
                    if (stachanged)
                    {
                        switch (MessageBox.Show("是否保存项目", "注意", MessageBoxButtons.YesNoCancel))
                        {
                            case System.Windows.Forms.DialogResult.OK:
                                cwsave.Excute();
                                break;
                            case System.Windows.Forms.DialogResult.No:
                                break;
                            case System.Windows.Forms.DialogResult.Cancel:
                                return;
                        }
                    }
                    xdb.Close();
                }
                else return;
            }
            if (gridsource != null)
            {
                gridsource.Clear();
            }
            try
            {
                xdb.Open(OpenProj.FileName);
                //fill info
                proj = (from p in xdb.Database.Query<DbProj>() select p).First();
                ProjecTitle.Text = proj.Title;
                staopened = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void MergeProj_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                var MergePath = Application.StartupPath + "/" + Guid.NewGuid().ToString() + "/";
                ZipFile zip = new ZipFile(MergeProj.FileName);
                zip.ExtractAll(MergePath);
                zip.Dispose();
                var ToBMerged = XDatabase.Open(MergePath);
                //ToBMerged.AutoSubmitMode = false;
                //fill info
                var mi = ToBMerged.Query<DbItem>();
                if (mi != null && mi.Count() > 0)
                {
                    foreach (var item in mi)
                    {
                        xdb.Database.Store(item);
                    }
                    stachanged = true;
                }
                ToBMerged.Close();
                Directory.Delete(MergePath, true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void FormIndexer_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (staopened)
            {
                if (stachanged)
                {
                    switch (MessageBox.Show("当前项目的更改尚未保存，是否保存？", "注意", MessageBoxButtons.YesNoCancel))
                    {
                        case System.Windows.Forms.DialogResult.Yes:
                            cwsave.Excute();
                            break;
                        case System.Windows.Forms.DialogResult.No:
                            break;
                        case System.Windows.Forms.DialogResult.Cancel:
                            e.Cancel = true;
                            return;
                    }
                }
            }
            if (xdb.IsOpened) xdb.Close();
#if LIC
            if (!ActivatorHelper.licensed)
            {
                MessageBox.Show("若您对适用满意请支持本程序，购买激活码获取更多功能！");
            }
#endif
        }

        #endregion

        #region Item-rela methods

        DbItem GetSelectedItem()
        {
            if (Grid.SelectedRows.Count > 0)
            {
                string id = (Grid.SelectedRows[0].Cells["ID"].Value as string);
                return (from i in xdb.Database.Query<DbItem>() where i.ID == id select i).First();
            }
            else return null;
        }

        private void Grid_SelectionChanged(object sender, EventArgs e)
        {
            if (Grid.SelectedRows.Count > 0)
            {
                staselected = true;
            }
            else staselected = false;
        }

        private void Grid_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            e.ThrowException = true;
        }

        #endregion

        private void MiExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void MiAbout_Click(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog();
        }

        private void MiCheckHelp_Click(object sender, EventArgs e)
        {
            string filename = Application.StartupPath + "/idxrh.pdf";
            if (File.Exists(filename))
            {
                Process.Start(filename);
            }
            else
            {
                MessageBox.Show("未能找到帮助文档");
            }
        }

        private void MiDocSave_Click(object sender, EventArgs e)
        {
            SaveDoc.ShowDialog();
        }

        private void SaveDoc_FileOk(object sender, CancelEventArgs e)
        {
            RtbMe.SaveFile(SaveDoc.FileName);
        }

        private void Grid_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (cwedit.Enabled)
            {
#if LIC
                if (ActivatorHelper.licensed)
                {
                    cwedit.Excute();
                }
                else
                {
                    MessageBox.Show("激活程序享有更多便捷！");
                }
#else
                cwedit.Excute();
#endif
            }
        }

    }
}
